//
//  Queue.m
//  VinSwiper
//
//  Created by siloon on 5/20/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "SLQueue.h"
#import "SLDebug.h"

@implementation SLQueue
#pragma mark -

- (id)init {
    self = [super init];
    if (self) {
		InitAndDeallocLog(@"Queue init");
		
        for(int i=0; i<SL_QUEUE_CAPACITY; i++){
			theQueue[i] = 0;
		}
		queueHeadIndex = 0;
		queueTailIndex = 0;
    }
    return self;
}

- (void)dealloc {
	InitAndDeallocLog(@"Queue dealloc");
	
	[self clearQueue];
    [super dealloc];
}

#pragma mark - queue

- (void)enqueue:(id)elem{
	@synchronized(self){
		if(elem == nil){
			NSException *ex = [NSException exceptionWithName:@"NullElementForQueue" 
													  reason:@"Null element for Queue" 
													userInfo:nil];
			[ex raise];
		}
		
		theQueue[queueTailIndex] = [elem retain];
		
		queueTailIndex ++;
		if(queueTailIndex >= SL_QUEUE_CAPACITY){
			queueTailIndex = 0;
		}
		
		if(queueTailIndex == queueHeadIndex){
			DebugLog(@"*** WARNING: Queue is full");
		}
		
		DebugLog(@"Queue enqueue: %d <=========> %d",queueHeadIndex,queueTailIndex);
	}
}

- (id)dequeue{
	@synchronized(self){
		if(queueHeadIndex == queueTailIndex){
			return nil;
		}
		
		id elem = [theQueue[queueHeadIndex] autorelease];
		theQueue[queueHeadIndex] = 0;
		
		queueHeadIndex ++;
		if(queueHeadIndex >= SL_QUEUE_CAPACITY){
			queueHeadIndex = 0;
		}
		
		DebugLog(@"Queue dequeue: %d <=========> %d",queueHeadIndex,queueTailIndex);
		
		return elem;
	}
}

- (id)peekFirst{
	@synchronized(self){
		if(queueHeadIndex == queueTailIndex){
			return nil;
		}
		
		id elem = theQueue[queueHeadIndex];
		
		DebugLog(@"Queue peekFirst: %d <=========> %d",queueHeadIndex,queueTailIndex);
		
		return elem;
	}
}

- (id)peekLast{
	@synchronized(self){
		if(queueHeadIndex == queueTailIndex){
			return nil;
		}
		
		int fixedTailIndex = queueTailIndex - 1;
		if(queueTailIndex == 0){
			fixedTailIndex = SL_QUEUE_CAPACITY - 1;
		}
		id elem = theQueue[fixedTailIndex];
		
		DebugLog(@"Queue peekLast: %d <=========> %d",queueHeadIndex,queueTailIndex);
		
		return elem;
	}
}

- (void)clearQueue{
	@synchronized(self){
		while(YES){
			id obj = [self dequeue];
			if(obj == 0){
				break;
			}
		}
	}
}

- (BOOL)isEmpty{
	@synchronized(self){
		return queueHeadIndex == queueTailIndex;
	}
}

- (NSString *)description{
	NSMutableString *str = [NSMutableString stringWithFormat:@"Queue: "];
	[str appendFormat:@"["];
	
	int headIndex = queueHeadIndex;
	
	BOOL isFirst = YES;
	while(1){
		if(headIndex == queueTailIndex){
			break;
		}
		
		id data = theQueue[headIndex];
		headIndex ++;
		
		if(headIndex >= SL_QUEUE_CAPACITY){
			headIndex = 0;
		}
		
		if(isFirst){
			isFirst = NO;
			
			[str appendFormat:@"[%@]",data];
			
		}else{
			
			[str appendFormat:@", [%@]",data];
			
		}
	}
	
	
	[str appendFormat:@"]"];
	
	return [NSString stringWithString:str];
}

@end
